    package modulo3.main;

import java.io.IOException;
import java.text.ChoiceFormat;
import java.text.Format;
import java.text.ParseException;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import modulo3.model.AtributoRecordatorio;
import modulo3.model.Prioridad;
import modulo3.model.Recordatorio;
import modulo3.model.Recordatorios;
import modulo3.model.SerializacionDeRecordatorios;
import modulo3.model.TipoRecordatorio;

/**
 *
 * @author jjsanche
 */
public class RecordatoriosTest {

    private static Scanner scanner = new Scanner(System.in);

    public static void main(String[] args) {
        Recordatorios recordatorios = SerializacionDeRecordatorios.desSerializarRecordatorios();
        
        if (recordatorios == null) {
            recordatorios = Recordatorios.getInstance();
            recordatorios.agregarRecordatorio("comprar comida para el perro", Prioridad.NORMAL);
            recordatorios.agregarRecordatorio("sacar la basura", Prioridad.ALTA);
            recordatorios.agregarRecordatorio("lavar los trastes", Prioridad.BAJA);
            recordatorios.agregarRecordatorio("barrer", Prioridad.ALTA);
            recordatorios.agregarRecordatorio("trapear", Prioridad.BAJA);
        }

        procesarMenu(recordatorios);
        
        try {
            SerializacionDeRecordatorios.serializarRecordatorios(recordatorios);
        } catch(IOException ioe) {
            System.err.println("Error al cerrar el archivo de serializacion");
            System.err.println(ioe.getMessage());
        }
    }

    public static void procesarMenu(Recordatorios recordatorios) {
        int opcion = 0;

        do {
            imprimirMenu();

            if (!scanner.hasNextInt()) {
                System.err.println("La opcion debe ser un numero");
                System.out.println();
                opcion = -1;
                continue;
            }

            opcion = scanner.nextInt();
            TipoRecordatorio tipo = null;
            Object valorAtributo = null;
            AtributoRecordatorio atributo = null;
            int numeroRecordatorio = 0;

            switch (opcion) {
                case 0: //salir
                    break;
                case 1: //Mostrar
                    System.out.println();
                    tipo = preguntarTipoRecordatorio();
                    System.out.println();
                    imprimirListaRecordatorios(recordatorios.getRecordatorios(tipo));
                    System.out.println();
                    break;
                case 2: //Marcar terminado
                    System.out.println();
                    imprimirListaRecordatorios(recordatorios.getRecordatorios(TipoRecordatorio.PENDIENTE));
                    System.out.println();
                    numeroRecordatorio = preguntarNumeroRecordatorio(recordatorios.getRecordatorios(TipoRecordatorio.PENDIENTE));
                    System.out.println();
                    marcarRecordatorioTerminado(numeroRecordatorio - 1, recordatorios);
                    break;
                case 3: //Ordenar
                    System.out.println();
                    tipo = preguntarTipoRecordatorio();
                    System.out.println();
                    atributo = preguntarAtributo(tipo);
                    recordatorios.ordenarRecordatorios(tipo, atributo);
                    System.out.println();
                    imprimirListaRecordatorios(recordatorios.getRecordatorios(tipo));
                    System.out.println();
                    break;
                case 4: //Filtrar
                    System.out.println();
                    tipo = preguntarTipoRecordatorio();
                    System.out.println();
                    atributo = preguntarAtributo(tipo);
                    System.out.println();
                    valorAtributo = preguntarValorAtributo(atributo);
                    List<Recordatorio> filtrados = recordatorios.filtrarRecordatorios(tipo, atributo, valorAtributo);
                    imprimirListaRecordatorios(filtrados);
                    System.out.println();
                    break;
                case 6:
                    System.out.println();
                    tipo = preguntarTipoRecordatorio();
                    System.out.println();
                    imprimirListaRecordatorios(recordatorios.getRecordatorios(tipo));
                    System.out.println();
                    numeroRecordatorio = preguntarNumeroRecordatorio(recordatorios.getRecordatorios(tipo));
                case 5: //Agregar
                    System.out.println();
                    String descripcion = preguntarDescripcion();
                    System.out.println();
                    valorAtributo = preguntarValorAtributo(AtributoRecordatorio.PRIORIDAD);
                    
                    if (opcion == 5) {
                        recordatorios.agregarRecordatorio(descripcion, (Prioridad) valorAtributo);
                        System.out.println("Recordatorio agregado.");
                    } else if (opcion == 6) {
                        recordatorios.modificarRecordatorio(tipo, numeroRecordatorio - 1, descripcion, (Prioridad) valorAtributo);
                        System.out.println("Recordatorio modificado.");
                    }
                    
                    System.out.println();
                    break;
                case 7: //Eliminar
                    System.out.println();
                    tipo = preguntarTipoRecordatorio();
                    System.out.println();
                    imprimirListaRecordatorios(recordatorios.getRecordatorios(tipo));
                    System.out.println();
                    numeroRecordatorio = preguntarNumeroRecordatorio(recordatorios.getRecordatorios(tipo));
                    System.out.println();
                    recordatorios.eliminarRecordatorio(tipo, numeroRecordatorio - 1);
                    System.out.println();
                    System.out.println("Lista actualizada: ");
                    imprimirListaRecordatorios(recordatorios.getRecordatorios(tipo));
                    System.out.println();
                    break;
                default:
                    System.err.println("Opcion incorrecta, intente de nuevo.");
                    System.out.println();
            }

            if (opcion != 0) {
                System.out.println("Presione Enter para continuar...");
                scanner.nextLine();
                scanner.nextLine();
            }
        } while (opcion != 0);
    }

    private static String preguntarDescripcion() {
        System.out.println("Introduzca la descripción del recordatorio: ");
        scanner.nextLine();
        
        return scanner.nextLine();
    }

    private static Object preguntarValorAtributo(AtributoRecordatorio atributo) {
        System.out.print("Ingrese el valor en el siguiente formato ");

        Format formatter;
        formatter = atributo.getFormat();

        if (atributo.getTipoClase() == Calendar.class) {
            System.out.println(((SimpleDateFormat) formatter).toPattern());

            boolean isFormatIncorrect = true;
            Calendar fecha = Calendar.getInstance();
            do {
                System.out.print("Ingrese fecha: ");

                String entrada = scanner.next();
                try {

                    isFormatIncorrect = false;
                    fecha.setTime(((SimpleDateFormat) formatter).parse(entrada));
                } catch (ParseException pe) {
                    isFormatIncorrect = true;
                    System.err.println("Formato incorrecto trate de nuevo usando el siguiente formato: "
                            + ((SimpleDateFormat) formatter).toPattern());
                }
            } while (isFormatIncorrect);

            return fecha;
        } else if (atributo.getTipoClase() == Prioridad.class) {
            ParsePosition status = new ParsePosition(1);
            System.out.println();

            StringBuilder pattern = new StringBuilder();

            for (double i = 1.0; i <= Prioridad.values().length; i++) {
                status.setIndex(0);
                pattern.append(((ChoiceFormat) formatter).parse(formatter.format(i), status).intValue()).append(" -> ").append(formatter.format(i).trim()).append("\n");
            }

            Map<Integer, Prioridad> prioridades = new HashMap<>();

            for (Prioridad prioridad : Prioridad.values()) {
                prioridades.put(prioridad.getValue(), prioridad);
            }

            System.out.println(pattern);
            Prioridad prioridadElegida = null;

            do {
                System.out.print("Ingrese la opción deseada: ");

                if (scanner.hasNextInt()) {
                    int entrada = scanner.nextInt();
                    prioridadElegida = prioridades.get(entrada);

                    if (prioridadElegida == null) {
                        System.err.println("Opcion incorrecta trate de nuevo usando el siguiente formato: ");
                        System.err.println(pattern);
                    }
                } else {
                    System.err.println("Formato incorrecto trate de nuevo usando el siguiente formato: ");
                    System.err.println(pattern);
                }
            } while (prioridadElegida == null);

            return prioridadElegida;
        }

        System.out.println(" ");
        return null;
    }

    private static void marcarRecordatorioTerminado(int indiceRecordatorio, Recordatorios recordatorios) {
        recordatorios.terminarRecordatorio(indiceRecordatorio);
    }

    private static int preguntarNumeroRecordatorio(List<Recordatorio> recordatorios) {
        int numero = 0;

        if (recordatorios.size() > 0) {
            do {
                System.out.print("Seleccione el número del recordatorio deseado: ");

                if (scanner.hasNextInt()) {
                    numero = scanner.nextInt();

                    if (numero < 1 || numero > recordatorios.size()) {
                        System.err.println("Número inválido para este tipo de recordatorios.");
                    }
                } else {
                    System.err.println("La opción debe ser un número");
                    numero = 0;
                }
            } while (numero < 1 || numero > recordatorios.size());
        } else {
            System.out.println("Por el momento no hay recordatorios a utilizar para esta operación.");
        }
        return numero;
    }

    private static AtributoRecordatorio preguntarAtributo(TipoRecordatorio tipo) {
        int opcion = 0;
        do {
            System.out.println("1.- Fecha");
            if (tipo == TipoRecordatorio.PENDIENTE) {
                System.out.println("2.- Prioridad");
            } else {
                System.out.println("2.- Fecha en que se terminó.");
            }

            System.out.print("Elija el atributo a usar en la operacion seleccionada: ");

            if (scanner.hasNextInt()) {
                opcion = scanner.nextInt();

                if (opcion != 1 && opcion != 2) {
                    System.err.println("Opcion incorrecta, intente de nuevo.");
                }
            } else {
                System.err.println("La opcion debe ser un numero");
                opcion = 0;
            }
        } while (opcion != 1 && opcion != 2);

        if (tipo == TipoRecordatorio.PENDIENTE) {
            return opcion == 1 ? AtributoRecordatorio.FECHA_REGISTRO : AtributoRecordatorio.PRIORIDAD;
        } else {
            return opcion == 1 ? AtributoRecordatorio.FECHA_REGISTRO : AtributoRecordatorio.FECHA_TERMINO;
        }
    }

    private static TipoRecordatorio preguntarTipoRecordatorio() {
        int opcion = 0;
        do {
            System.out.println("1.- Pendientes");
            System.out.println("2.- Terminados");
            System.out.print("Elija un tipo de recordatorio: ");

            if (scanner.hasNextInt()) {
                opcion = scanner.nextInt();

                if (opcion != 1 && opcion != 2) {
                    System.err.println("Opcion incorrecta, intente de nuevo.");
                }
            } else {
                System.err.println("La opcion debe ser un numero");
                opcion = 0;
            }
        } while (opcion != 1 && opcion != 2);

        return opcion == 1 ? TipoRecordatorio.PENDIENTE : TipoRecordatorio.TERMINADO;
    }

    private static void imprimirListaRecordatorios(List<Recordatorio> lista) {
        if (lista.isEmpty()) {
            System.out.println("No hay recordatorios de este tipo en este momento.");
        } else {
            for (int i = 0; i < lista.size(); i++) {
                System.out.println((i + 1) + ".- " + lista.get(i).toString());
            }
        }
    }

    private static void imprimirMenu() {
        System.out.println("Menu");
        System.out.println("1.- Mostrar recordatorios");
        System.out.println("2.- Marcar recordatorios terminados");
        System.out.println("3.- Ordenar recordatorios");
        System.out.println("4.- Filtrar recordatorios");
        System.out.println("5.- Agregar recordatorio");
        System.out.println("6.- Modificar recordatorio");
        System.out.println("7.- Eliminar recordatorio");
        System.out.println("0.- Salir");
        System.out.print("Elija una opcion: ");
    }
}